package cn.cyh.queue_service.websocket;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 队列状态WebSocket处理器
 */
// 注释掉@Component以避免Bean定义冲突
// @Component
@Slf4j
public class QueueStatusWebSocketHandler extends TextWebSocketHandler {

    /**
     * 存储所有连接的会话
     */
    private static final Map<String, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();

    /**
     * 按排队号码分组的会话
     */
    public static final Map<String, WebSocketSession> QUEUE_NUMBER_SESSIONS = new ConcurrentHashMap<>();

    /**
     * 处理连接建立
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        log.info("队列状态连接已建立: {}", session.getId());
        SESSIONS.put(session.getId(), session);

        // 解析业务类型ID
        log.info("客户端已订阅业务类型 {}", session.getId());
        SocketMsg msg = new SocketMsg();
        msg.setType("connect");
        msg.setData(session.getId());
        broadcastMessage(session, JSONUtil.toJsonStr(msg));
        CurrentQueues.sessionMap.put(session.getId(), session);
    }

    /**
     * 处理消息
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        log.debug(session.getId() + "收到消息: {}", message.getPayload());
    }

    /**
     * 处理连接关闭
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        log.info("队列状态连接已关闭: {}, 状态: {}", session.getId(), status);
        SESSIONS.remove(session.getId());
        CurrentQueues.sessionMap.remove(session.getId(), session);
        // 从排队号码会话中移除
        String queueNumber = getQueueNumber(session);
        if (queueNumber != null) {
            QUEUE_NUMBER_SESSIONS.remove(queueNumber);
        }
    }

    /**
     * 处理传输错误
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        log.error("队列状态传输错误: {}", exception.getMessage(), exception);
        
        try {
            session.close(CloseStatus.SERVER_ERROR);
        } catch (IOException e) {
            log.error("关闭会话时发生错误: {}", e.getMessage(), e);
        }
    }

    /**
     * 广播队列状态消息给所有客户端
     */
    public void broadcastQueueStatusMessage(QueueStatusMessage message) {
        String payload = JSONUtil.toJsonStr(message);
        broadcastMessage(payload);
    }

    /**
     * 广播队列状态消息给所有客户端
     */
    public void broadcastQueueStatusMessageToBusinessType(QueueStatusMessage message) {
        String payload = JSONUtil.toJsonStr(message);
        broadcastMessageToBusinessType(payload);
    }

    /**
     * 发送队列状态消息给指定排队号码的客户端
     */
    public void sendQueueStatusMessageToQueueNumber(String queueNumber, QueueStatusMessage message) {
        String payload = JSONUtil.toJsonStr(message);
        WebSocketSession session = QUEUE_NUMBER_SESSIONS.get(queueNumber);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(payload));
            } catch (IOException e) {
                log.error("发送消息到排队号码 {} 时发生错误: {}", queueNumber, e.getMessage(), e);
            }
        }
    }

    /**
     * 广播消息给所有客户端
     */
    private void broadcastMessage(String message) {
        SESSIONS.values().forEach(session -> {
            try {
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage(message));
                }
            } catch (IOException e) {
                log.error("发送消息时发生错误: {}", e.getMessage(), e);
            }
        });
    }

    /**
     * 给指定客户端发消息
     */
    private void broadcastMessage(WebSocketSession session, String message) {
        try {
            if (session.isOpen()) {
                session.sendMessage(new TextMessage(message));
            }
        } catch (IOException e) {
            log.error("发送消息时发生错误: {}", e.getMessage(), e);
        }
    }

    /**
     * 广播消息给所有客户端
     */
    private void broadcastMessageToBusinessType(String message) {
        SESSIONS.values().forEach(session -> broadcastMessage(session, message));
    }

    /**
     * 从会话中获取业务类型ID
     */
    private Integer getBusinessTypeId(WebSocketSession session) {
        Map<String, String> attributes = getUriParam(session);
        Object businessTypeId = attributes.get("businessTypeId");
        if (businessTypeId != null) {
            return Integer.valueOf(businessTypeId.toString());
        }
        return null;
    }

    public Map<String, String> getUriParam(WebSocketSession session) {
        String rawQuery = Objects.requireNonNull(session.getUri()).getRawQuery();
        String[] paramStrs = rawQuery.split("&");
        if (paramStrs.length > 0) {
            Map<String, String> param = new HashMap<>(paramStrs.length);
            for (String paramStrEntry : paramStrs) {
                String[] paramStr = paramStrEntry.split("=");
                if (paramStr.length == 2) {
                    param.put(paramStr[0], paramStr[1]);
                }
            }
            return param;
        } else {
            return null;
        }
    }

    /**
     * 从会话中获取排队号码
     */
    private String getQueueNumber(WebSocketSession session) {
        Map<String, Object> attributes = session.getAttributes();
        return (String) attributes.getOrDefault("queueNumber", null);
    }
} 